Using ts-node with Global Types
Like many TypeScript projects, I’m using mocha to run
tests via ts-node
. Everything was
working great until the project needed to introduce a global variable requiring
a global.d.ts
type declaration file. Compiling the project worked, but
ts-node
seemingly couldn’t find the type declaration.
Updated: 12/30/21 for recent versions of TypeScript/ts-node
We can use declare
to tell TypeScript that global
contains a property with
a given type.
declare global
let myGlobal: number
}
Now we’re able to set global.myGlobal
in the application without type errors.
For older versions of TypeScript
Getting right into it with a contrived example, given a global.d.ts
declaring
a global variable, named myGlobal
:
declare const myGlobal: number
namespace NodeJS {
interface Global {
myGlobal: number
}
}
And a file that defines the global via global.myGlobal = 100
, now any script
that uses myGlobal
via ts-node
will fail with the following error:
TSError: ⨯ Unable to compile TypeScript:
test/mainTest.ts:3:17 - error TS2552: Cannot find name 'myGlobal'.
This is happening because ts-node
isn’t looking for global.d.ts
file. After
doing some research the first time I ran into this, I found two common
suggestions:
- Pass the
--files
flag tots-node
sots-node
will compile all TypeScript files defined by yourtsconfig
sfiles
key. The large downside here being that each time you usets-node
all of those files will be compiled resulting in slower startup time. - Define
typeRoots
. Again, this works, but you no longer have automatic type declaration detection.
Because of the downsides each solution came with, I searched for a better approach and thankfully, found one. Well, two.
The first option was to use a triple slash directive to associate the file that declares the global value with the declaration file.
/// <reference types="./global" />
global.myGlobal = 100
Note: Omit the .d.ts
file extension.
This effectively says ‘this file depends on these types, when importing me
please import the types too’. Running npx tsc
completed successfully, as did
our ts-node
powered mocha tests.
The next solution seemed almost obvious after I found it. The global.d.ts
file
can be imported.
import "./global.d"
global.myGlobal = 100
Now running tsc
and our ts-node
script, both complete successfully.
It took a bit of trial, error, and google, but I’m pretty happy with how simple the solution ended up being.